/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package server.entidades;

import comum.Message;
import comum.ValidaUtil;
import java.io.IOException;
import java.net.Socket;
import java.util.Observable;
import java.util.Observer;
import server.Server;
import server.colecoes.ColecaoCanal;

/**
 *
 * @author root
 */
public class User extends Peer implements Observer {

    private String nickname;
    private String oldnick;
    private String username;
    private boolean respondeuping;
    private ColecaoCanal canais = new ColecaoCanal();
    private boolean conectado = false;
    private Interpretador interpretador;

    public synchronized String getNickname() {
        return nickname;
    }

    public synchronized String getRealname() {
        return realname;
    }
    private String realname;

    public User(Server parent, Socket socket) {
        super(parent, socket);
        this.interpretador = new Interpretador(parent, this);
    }

    @Override
    public String toString() {
        return nickname;
    }

    @Override
    public void init() {
        transmitirMensagem(new Message(":" + parent.getServerHost() + " NOTICE * :*** Looking up your hostname..."));
    }

    @Override
    public synchronized void tratarMessage(Message m) {
        interpretador.tratarMessage(m);
    }

    public synchronized void joinChannel(String nomecanal) {
        Channel c = parent.getCanais().getCanalPorNome(nomecanal);
        if (c == null) {
            c = new Channel(parent, nomecanal);
            parent.getCanais().adicionarCanal(c);
        }
        c.addUser(this);
        canais.adicionarCanal(c);
        System.out.println(">> " + nickname + " entrou no canal " + c.getNome());
    }

    public synchronized void partChannel(String nomecanal) {
        Channel c = parent.getCanais().getCanalPorNome(nomecanal);
        if (c != null) {
            c.partUser(this);
            canais.removerCanal(c);
            System.out.println(">> " + nickname + " saiu do canal " + c.getNome());
        }
    }

    public synchronized String getHost() {
        return this.socket.getInetAddress().getHostAddress();
    }

    public synchronized void transmitirMensagem(Message msg) {
        if (isConectado() && socket.isConnected() && !socket.isOutputShutdown()) {
            try {
                out.write(msg.toString() + "\n");
                out.flush();
            } catch (IOException ex) {
//                System.out.println("ERRO AO ENVIAR \"" + msg.toString() + "\" para " + nickname);
                parent.finalizarUsuario(this);
            }
        } else {
            parent.finalizarUsuario(this);
        }
    }

    public synchronized String getStringName() {
        return this.nickname;
    }

    public synchronized boolean isChannel() {
        return false;
    }

    public synchronized boolean isUser() {
        return true;
    }

    public synchronized void ping() {
//        Ping p = new Ping(this, 10000);
//        new Thread(p).start();
//        p.addObserver(this);
    }

    public synchronized void sendMotd() {
        transmitirMensagem(new Message(":" + parent.getServerHost() + " 001 " + nickname + " :Welcome to the " + parent.getName() + " Internet Relay Chat Server, " + nickname + "!"));
        transmitirMensagem(new Message(":" + parent.getServerHost() + " 251 " + nickname + " :There are " + parent.getUsuarios().getUsuarios().size() + " users on 1 server"));
        transmitirMensagem(new Message(":" + parent.getServerHost() + " 252 " + nickname + " :There are no Ircops online"));
        transmitirMensagem(new Message(":" + parent.getServerHost() + " 375 " + nickname + " :Inicio do MOTD"));
        transmitirMensagem(new Message(":" + parent.getServerHost() + " 372 " + nickname + " :Essa é a mensagem do dia!"));
        transmitirMensagem(new Message(":" + parent.getServerHost() + " 376 " + nickname + " :Fim do MOTD"));

    }

    public synchronized void update(Observable o, Object arg) {
//        if (o instanceof Ping) {
//            if (arg instanceof String && ((String) arg).equals("pingou")) {
//                this.respondeuping = false;
//            } else if (!respondeuping) {
//                parent.finalizarUsuario(this);
//            }
//        }
    }

    public synchronized String getUsername() {
        return username;
    }

    public synchronized void atualizarNick(String tempnick) {
        if (parent.getUsuarios().getUsuarioPorNick(tempnick) == null) {
            oldnick = nickname;
            this.nickname = tempnick;
            Message m = new Message(":" + oldnick + "!" + username + "@" + getHost() + " NICK :" + nickname);
            transmitirMensagem(m);
            System.out.println(">> " + oldnick + " agora se chama " + nickname);
        }
    }

    public synchronized void setNickname(String tempnick) {
        // inicializa nickname
        if (parent.getUsuarios().getUsuarioPorNick(tempnick) == null) {
            this.nickname = tempnick;
            System.out.println(">> " + nickname + " conectou.");
            conectado = true;
        } else {
            parent.finalizarUsuario(this);
        }
    }

    public synchronized boolean isConectado() {
        return (conectado && socket.isConnected() && !socket.isOutputShutdown());
    }

    public void setRespondeuPing(boolean b) {
        this.respondeuping = b;
    }

    public void setRealName(String newname) {
        this.realname = newname;
    }

    public void setUserName(String newusername) {
        this.username = newusername;
    }

    @Override
    public void stop() {
        run = false;
        try {
            in.close();
            out.close();
            socket.close();
            conectado = false;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void finalizar() {
        parent.finalizarUsuario(this);
    }
}
